{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "ee57e9b7-a90f-4783-b607-ba66a88c5ae0",
   "metadata": {},
   "outputs": [],
   "source": [
    "import pyspark\n",
    "import yaml\n",
    "import numpy as np\n",
    "import pandas as pd\n",
    "import warnings\n",
    "\n",
    "warnings.filterwarnings('ignore')\n",
    "pd.set_option('display.max_rows', None)\n",
    "pd.set_option('display.max_columns', None)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "bfd8fffd-68ea-4711-9c29-1bba4ebe14a8",
   "metadata": {},
   "outputs": [],
   "source": [
    "def init_spark():\n",
    "    spark = pyspark.sql.SparkSession.builder\\\n",
    "            .master(\"local\")\\\n",
    "            .appName(\"Credit Score Card\") \\\n",
    "            .config(\"spark.executor.memory\",\"8G\") \\\n",
    "            .config(\"spark.executor.instances\",\"1\") \\\n",
    "            .config(\"spark.executor.cores\", \"4\") \\\n",
    "            .config(\"spark.default.parallelism\", 400) \\\n",
    "            .config(\"spark.executor.memoryOverhead\", \"2G\") \\\n",
    "            .getOrCreate()\n",
    "    sc = spark.sparkContext\n",
    "    print(sc.version)\n",
    "    print(sc.applicationId)\n",
    "    print(sc.uiWebUrl)\n",
    "    return spark\n",
    "\n",
    "def load_config(path):\n",
    "    params = dict()\n",
    "    with open(path, 'r') as stream:\n",
    "        params = yaml.load(stream, Loader=yaml.FullLoader)\n",
    "    return params\n",
    "\n",
    "def read_dataset(spark, data_path, file_format='csv'):\n",
    "    dataset = spark.read.format(file_format)\\\n",
    "      .option(\"header\",  True)\\\n",
    "      .option(\"inferSchema\",  True)\\\n",
    "      .load(data_path)  \n",
    "    return dataset"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "8cf66859-6c7b-4f73-912f-946eca394546",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING: An illegal reflective access operation has occurred\n",
      "WARNING: Illegal reflective access by org.apache.spark.unsafe.Platform (file:/opt/spark/jars/spark-unsafe_2.12-3.1.2.jar) to constructor java.nio.DirectByteBuffer(long,int)\n",
      "WARNING: Please consider reporting this to the maintainers of org.apache.spark.unsafe.Platform\n",
      "WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations\n",
      "WARNING: All illegal access operations will be denied in a future release\n",
      "22/06/09 04:29:07 WARN NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable\n",
      "Using Spark's default log4j profile: org/apache/spark/log4j-defaults.properties\n",
      "Setting default log level to \"WARN\".\n",
      "To adjust logging level use sc.setLogLevel(newLevel). For SparkR, use setLogLevel(newLevel).\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "3.1.2\n",
      "local-1654748948259\n",
      "http://jupyter.my.nginx.test/hub/user-redirect/proxy/4040/jobs/\n"
     ]
    }
   ],
   "source": [
    "spark = init_spark()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "e4a2d188-7608-4035-9ad4-dce6d9848126",
   "metadata": {},
   "outputs": [],
   "source": [
    "params = load_config('../conf/default_estimation_spark_lgbm_dev.yaml')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "94a25420-132f-4119-b84f-d868ac26292f",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "                                                                                \r"
     ]
    }
   ],
   "source": [
    "eval_test_dataset = read_dataset(spark, params['eval_out_path'], file_format='parquet')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "b001fc90-0225-4879-a63e-802a8b1c4ca2",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "                                                                                \r"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>isDefault</th>\n",
       "      <th>features</th>\n",
       "      <th>rawPrediction</th>\n",
       "      <th>probability</th>\n",
       "      <th>prediction</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0</td>\n",
       "      <td>[1000.0, 3.0, 6.97, 30.87, 1.0, 2.0, 123318.0,...</td>\n",
       "      <td>[2.337995530153171, -2.337995530153171]</td>\n",
       "      <td>[0.911975306477623, 0.088024693522377]</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0</td>\n",
       "      <td>[1000.0, 3.0, 15.99, 35.16, 3.0, 14.0, 215340....</td>\n",
       "      <td>[-0.10965281459904996, 0.10965281459904996]</td>\n",
       "      <td>[0.4726142307997735, 0.5273857692002265]</td>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0</td>\n",
       "      <td>[1000.0, 3.0, 18.24, 36.28, 4.0, 19.0, 64536.0...</td>\n",
       "      <td>[0.32907556139404964, -0.32907556139404964]</td>\n",
       "      <td>[0.5815344297028524, 0.41846557029714754]</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>1</td>\n",
       "      <td>[1500.0, 3.0, 11.49, 49.46, 2.0, 9.0, 212874.0...</td>\n",
       "      <td>[0.8718348674582469, -0.8718348674582469]</td>\n",
       "      <td>[0.7051273522619355, 0.2948726477380646]</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0</td>\n",
       "      <td>[1500.0, 3.0, 13.49, 50.9, 3.0, 11.0, 89676.0,...</td>\n",
       "      <td>[-0.1605600898253861, 0.1605600898253861]</td>\n",
       "      <td>[0.45994598843603185, 0.5400540115639682]</td>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>1</td>\n",
       "      <td>[1500.0, 3.0, 16.99, 53.48, 4.0, 17.0, 6600.0,...</td>\n",
       "      <td>[-0.4225961586637862, 0.4225961586637862]</td>\n",
       "      <td>[0.39589567937414427, 0.6041043206258557]</td>\n",
       "      <td>1.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>0</td>\n",
       "      <td>[1600.0, 3.0, 10.64, 52.11, 2.0, 8.0, 203091.0...</td>\n",
       "      <td>[0.9316509455109415, -0.9316509455109415]</td>\n",
       "      <td>[0.7174101064763352, 0.2825898935236648]</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>0</td>\n",
       "      <td>[1600.0, 3.0, 13.53, 54.32, 2.0, 9.0, 65718.0,...</td>\n",
       "      <td>[1.2519325976063975, -1.2519325976063975]</td>\n",
       "      <td>[0.777634223779675, 0.22236577622032502]</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>0</td>\n",
       "      <td>[1800.0, 3.0, 12.73, 60.42, 2.0, 9.0, 61357.0,...</td>\n",
       "      <td>[2.783424036088894, -2.783424036088894]</td>\n",
       "      <td>[0.9417734897923757, 0.05822651020762423]</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>0</td>\n",
       "      <td>[1800.0, 3.0, 19.99, 66.89, 5.0, 20.0, 234119....</td>\n",
       "      <td>[0.2507570877638907, -0.2507570877638907]</td>\n",
       "      <td>[0.5623628372077925, 0.4376371627922075]</td>\n",
       "      <td>0.0</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   isDefault                                           features  \\\n",
       "0          0  [1000.0, 3.0, 6.97, 30.87, 1.0, 2.0, 123318.0,...   \n",
       "1          0  [1000.0, 3.0, 15.99, 35.16, 3.0, 14.0, 215340....   \n",
       "2          0  [1000.0, 3.0, 18.24, 36.28, 4.0, 19.0, 64536.0...   \n",
       "3          1  [1500.0, 3.0, 11.49, 49.46, 2.0, 9.0, 212874.0...   \n",
       "4          0  [1500.0, 3.0, 13.49, 50.9, 3.0, 11.0, 89676.0,...   \n",
       "5          1  [1500.0, 3.0, 16.99, 53.48, 4.0, 17.0, 6600.0,...   \n",
       "6          0  [1600.0, 3.0, 10.64, 52.11, 2.0, 8.0, 203091.0...   \n",
       "7          0  [1600.0, 3.0, 13.53, 54.32, 2.0, 9.0, 65718.0,...   \n",
       "8          0  [1800.0, 3.0, 12.73, 60.42, 2.0, 9.0, 61357.0,...   \n",
       "9          0  [1800.0, 3.0, 19.99, 66.89, 5.0, 20.0, 234119....   \n",
       "\n",
       "                                 rawPrediction  \\\n",
       "0      [2.337995530153171, -2.337995530153171]   \n",
       "1  [-0.10965281459904996, 0.10965281459904996]   \n",
       "2  [0.32907556139404964, -0.32907556139404964]   \n",
       "3    [0.8718348674582469, -0.8718348674582469]   \n",
       "4    [-0.1605600898253861, 0.1605600898253861]   \n",
       "5    [-0.4225961586637862, 0.4225961586637862]   \n",
       "6    [0.9316509455109415, -0.9316509455109415]   \n",
       "7    [1.2519325976063975, -1.2519325976063975]   \n",
       "8      [2.783424036088894, -2.783424036088894]   \n",
       "9    [0.2507570877638907, -0.2507570877638907]   \n",
       "\n",
       "                                 probability  prediction  \n",
       "0     [0.911975306477623, 0.088024693522377]         0.0  \n",
       "1   [0.4726142307997735, 0.5273857692002265]         1.0  \n",
       "2  [0.5815344297028524, 0.41846557029714754]         0.0  \n",
       "3   [0.7051273522619355, 0.2948726477380646]         0.0  \n",
       "4  [0.45994598843603185, 0.5400540115639682]         1.0  \n",
       "5  [0.39589567937414427, 0.6041043206258557]         1.0  \n",
       "6   [0.7174101064763352, 0.2825898935236648]         0.0  \n",
       "7   [0.777634223779675, 0.22236577622032502]         0.0  \n",
       "8  [0.9417734897923757, 0.05822651020762423]         0.0  \n",
       "9   [0.5623628372077925, 0.4376371627922075]         0.0  "
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "eval_test_dataset.limit(10).toPandas()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "be926b5a-e31f-494e-a76a-f30ba4fab281",
   "metadata": {},
   "source": [
    "Assuming that we have reasonably estimated the loan default rate $p$ through the machine learning model, then we can give the following score\n",
    "\n",
    "\\begin{aligned}\n",
    "\\text{Score} &= A-B \\ln(\\text{odds})= A-B \\ln\\bigg( \\frac{p}{1-p} \\bigg) \\\\\n",
    "B &= \\frac{\\text{PDO}}{{\\ln2}} \\\\\n",
    "A &= \\text{S}_0 - B \\ln(\\text{odds}_0) \\\\\n",
    "\\end{aligned}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "46f4f4bb-1e47-40a7-9caf-de2f01ab8f5c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "PDO=20, B=28.85, A=580.00\n"
     ]
    }
   ],
   "source": [
    "## Define PDO, S0, odds0\n",
    "PDO = 20\n",
    "S0 = 600\n",
    "odds0 = 1/2\n",
    "\n",
    "B = PDO / np.log(2)\n",
    "A = S0 + B * np.log(odds0)\n",
    "print(\"PDO=%d, B=%.2f, A=%.2f\"%(PDO, B, A))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "cbe5697b-f216-4360-9b0f-05b6910480bf",
   "metadata": {},
   "outputs": [],
   "source": [
    "from pyspark.sql import functions as F\n",
    "from pyspark.sql.types import DoubleType\n",
    "from pyspark.sql.functions import udf, col\n",
    "\n",
    "def compute_credit_score(v):\n",
    "    try:\n",
    "        return float(A-B*np.log(float(v[1])/float(v[0])))\n",
    "    except ValueError:\n",
    "        return -1.0\n",
    "\n",
    "credit_score_udf = udf(compute_credit_score, DoubleType())\n",
    "\n",
    "result = eval_test_dataset.withColumn('credit_score', credit_score_udf(F.col(\"probability\")))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "3698418e-2700-4279-a4c3-91bb1f74ab62",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "                                                                                \r"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>isDefault</th>\n",
       "      <th>features</th>\n",
       "      <th>rawPrediction</th>\n",
       "      <th>probability</th>\n",
       "      <th>prediction</th>\n",
       "      <th>credit_score</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>0</td>\n",
       "      <td>[1000.0, 3.0, 6.97, 30.87, 1.0, 2.0, 123318.0,...</td>\n",
       "      <td>[2.337995530153171, -2.337995530153171]</td>\n",
       "      <td>[0.911975306477623, 0.088024693522377]</td>\n",
       "      <td>0.0</td>\n",
       "      <td>647.460291</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>0</td>\n",
       "      <td>[1000.0, 3.0, 15.99, 35.16, 3.0, 14.0, 215340....</td>\n",
       "      <td>[-0.10965281459904996, 0.10965281459904996]</td>\n",
       "      <td>[0.4726142307997735, 0.5273857692002265]</td>\n",
       "      <td>1.0</td>\n",
       "      <td>576.836089</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>0</td>\n",
       "      <td>[1000.0, 3.0, 18.24, 36.28, 4.0, 19.0, 64536.0...</td>\n",
       "      <td>[0.32907556139404964, -0.32907556139404964]</td>\n",
       "      <td>[0.5815344297028524, 0.41846557029714754]</td>\n",
       "      <td>0.0</td>\n",
       "      <td>589.495114</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>1</td>\n",
       "      <td>[1500.0, 3.0, 11.49, 49.46, 2.0, 9.0, 212874.0...</td>\n",
       "      <td>[0.8718348674582469, -0.8718348674582469]</td>\n",
       "      <td>[0.7051273522619355, 0.2948726477380646]</td>\n",
       "      <td>0.0</td>\n",
       "      <td>605.155837</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>0</td>\n",
       "      <td>[1500.0, 3.0, 13.49, 50.9, 3.0, 11.0, 89676.0,...</td>\n",
       "      <td>[-0.1605600898253861, 0.1605600898253861]</td>\n",
       "      <td>[0.45994598843603185, 0.5400540115639682]</td>\n",
       "      <td>1.0</td>\n",
       "      <td>575.367215</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>5</th>\n",
       "      <td>1</td>\n",
       "      <td>[1500.0, 3.0, 16.99, 53.48, 4.0, 17.0, 6600.0,...</td>\n",
       "      <td>[-0.4225961586637862, 0.4225961586637862]</td>\n",
       "      <td>[0.39589567937414427, 0.6041043206258557]</td>\n",
       "      <td>1.0</td>\n",
       "      <td>567.806452</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6</th>\n",
       "      <td>0</td>\n",
       "      <td>[1600.0, 3.0, 10.64, 52.11, 2.0, 8.0, 203091.0...</td>\n",
       "      <td>[0.9316509455109415, -0.9316509455109415]</td>\n",
       "      <td>[0.7174101064763352, 0.2825898935236648]</td>\n",
       "      <td>0.0</td>\n",
       "      <td>606.881764</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>7</th>\n",
       "      <td>0</td>\n",
       "      <td>[1600.0, 3.0, 13.53, 54.32, 2.0, 9.0, 65718.0,...</td>\n",
       "      <td>[1.2519325976063975, -1.2519325976063975]</td>\n",
       "      <td>[0.777634223779675, 0.22236577622032502]</td>\n",
       "      <td>0.0</td>\n",
       "      <td>616.123139</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>8</th>\n",
       "      <td>0</td>\n",
       "      <td>[1800.0, 3.0, 12.73, 60.42, 2.0, 9.0, 61357.0,...</td>\n",
       "      <td>[2.783424036088894, -2.783424036088894]</td>\n",
       "      <td>[0.9417734897923757, 0.05822651020762423]</td>\n",
       "      <td>0.0</td>\n",
       "      <td>660.312641</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>9</th>\n",
       "      <td>0</td>\n",
       "      <td>[1800.0, 3.0, 19.99, 66.89, 5.0, 20.0, 234119....</td>\n",
       "      <td>[0.2507570877638907, -0.2507570877638907]</td>\n",
       "      <td>[0.5623628372077925, 0.4376371627922075]</td>\n",
       "      <td>0.0</td>\n",
       "      <td>587.235320</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "   isDefault                                           features  \\\n",
       "0          0  [1000.0, 3.0, 6.97, 30.87, 1.0, 2.0, 123318.0,...   \n",
       "1          0  [1000.0, 3.0, 15.99, 35.16, 3.0, 14.0, 215340....   \n",
       "2          0  [1000.0, 3.0, 18.24, 36.28, 4.0, 19.0, 64536.0...   \n",
       "3          1  [1500.0, 3.0, 11.49, 49.46, 2.0, 9.0, 212874.0...   \n",
       "4          0  [1500.0, 3.0, 13.49, 50.9, 3.0, 11.0, 89676.0,...   \n",
       "5          1  [1500.0, 3.0, 16.99, 53.48, 4.0, 17.0, 6600.0,...   \n",
       "6          0  [1600.0, 3.0, 10.64, 52.11, 2.0, 8.0, 203091.0...   \n",
       "7          0  [1600.0, 3.0, 13.53, 54.32, 2.0, 9.0, 65718.0,...   \n",
       "8          0  [1800.0, 3.0, 12.73, 60.42, 2.0, 9.0, 61357.0,...   \n",
       "9          0  [1800.0, 3.0, 19.99, 66.89, 5.0, 20.0, 234119....   \n",
       "\n",
       "                                 rawPrediction  \\\n",
       "0      [2.337995530153171, -2.337995530153171]   \n",
       "1  [-0.10965281459904996, 0.10965281459904996]   \n",
       "2  [0.32907556139404964, -0.32907556139404964]   \n",
       "3    [0.8718348674582469, -0.8718348674582469]   \n",
       "4    [-0.1605600898253861, 0.1605600898253861]   \n",
       "5    [-0.4225961586637862, 0.4225961586637862]   \n",
       "6    [0.9316509455109415, -0.9316509455109415]   \n",
       "7    [1.2519325976063975, -1.2519325976063975]   \n",
       "8      [2.783424036088894, -2.783424036088894]   \n",
       "9    [0.2507570877638907, -0.2507570877638907]   \n",
       "\n",
       "                                 probability  prediction  credit_score  \n",
       "0     [0.911975306477623, 0.088024693522377]         0.0    647.460291  \n",
       "1   [0.4726142307997735, 0.5273857692002265]         1.0    576.836089  \n",
       "2  [0.5815344297028524, 0.41846557029714754]         0.0    589.495114  \n",
       "3   [0.7051273522619355, 0.2948726477380646]         0.0    605.155837  \n",
       "4  [0.45994598843603185, 0.5400540115639682]         1.0    575.367215  \n",
       "5  [0.39589567937414427, 0.6041043206258557]         1.0    567.806452  \n",
       "6   [0.7174101064763352, 0.2825898935236648]         0.0    606.881764  \n",
       "7   [0.777634223779675, 0.22236577622032502]         0.0    616.123139  \n",
       "8  [0.9417734897923757, 0.05822651020762423]         0.0    660.312641  \n",
       "9   [0.5623628372077925, 0.4376371627922075]         0.0    587.235320  "
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "result.limit(10).toPandas()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e61cde22-85cf-482d-ae10-3298749f1280",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
